home *** CD-ROM | disk | FTP | other *** search
/ DS-CD ROM 2 1993 August / DS CD-ROM 2.Ausgabe (August 1993).iso / programm / ds0256 / mdebug22.exe / BSP.PRT < prev    next >
Text File  |  1992-11-01  |  51KB  |  1,741 lines

  1.     ───────────────────────────────────────────────────────────────────
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.                                  MDEBUG
  10.  
  11.                              Version  V2.05
  12.  
  13.                  Highperformance Debugging Tool für PCs
  14.  
  15.                   Beispiele für die Nutzung von MDEBUG
  16.  
  17.                            Copyright 1992 by
  18.                              Bernd Schemmer
  19.                           All Rights reserved.
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.     ───────────────────────────────────────────────────────────────────
  64.     Credits
  65.  
  66.     MDEBUG wurde geschrieben von Bernd Schemmer.
  67.  
  68.  
  69.     ───────────────────────────────────────────────────────────────────
  70.     Copyright
  71.  
  72.     MDEBUG ist Copyright 1992 by Bernd Schemmer
  73.  
  74.     Dieses Dokument ist Copyright 1992 by Bernd Schemmer
  75.  
  76.  
  77.     ───────────────────────────────────────────────────────────────────
  78.     Eingetragene Warenzeichen, Warennamen
  79.  
  80.     Warenamen und eingetragene Warenzeichen werden in diesem Text ohne
  81.     Gewährleistung  einer freien Verwendung benutzt.
  82.     Alle  benutzten  Warenanamen  und  eingetragenen Warenzeichen sind
  83.     Eigentum  ihrer jeweiligen Besitzer.
  84.  
  85.  
  86.     ───────────────────────────────────────────────────────────────────
  87.     Granatie-Ausschluß-Erklärung
  88.  
  89.  
  90.     Bernd Schemmer  gibt keine  Garantien irgendeiner  Art,  weder aus-
  91.     drücklich noch implizit, einschliesslich unbegrenzt aller Garantien
  92.     der  Verwendbarkeit  und/oder  Nichtverwendbarkeit  für irgendeinen
  93.     Zweck.  Bernd Schemmer  übernimmt  keine  Verpflichtungen  für  den
  94.     Gebrauchswert dieser Software  über den  Kaufpreis  dieser Software
  95.     hinaus.  Unter  keinen  Umständen  ist  Bernd Schemmer haftbar  für
  96.     jedwede Folgeschäden, einschliesslich aller entgangenen Gewinne und
  97.     Vermögensverluste,  oder  anderer   mittelbarer  und  unmittelbarer
  98.     Schäden,  die  durch  den  Gebrauch  oder  die  Nichtverwendbarkeit
  99.     dieser Software  und ihrer  begleitenden  Dokumentation  entstehen.
  100.     Dies gilt  auch  dann,  wenn  Bernd Schemmer  über die  Möglichkeit
  101.     solcher  Schäden unterrichtet  war oder ist.
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.     ───────────────────────────────────────────────────────────────────
  120.  
  121.  
  122.  
  123.  
  124.  
  125.     Inhalt                                                 Seite
  126.     ────────────────────────────────────────────────────────────
  127.  
  128.  
  129.     Einleitung ...........................................     1
  130.     Verwendete Syntax in den Beispielen ..................     2
  131.     Allgemeine Hinweise zur Benutzung ....................     2
  132.     Tips für die Benutzung von MDEBUG ....................     2
  133.     Beispiele für die Interpreter-Befehle ................     4
  134.     Normalisieren einer Adresse ..........................     4
  135.     Rechnen mit Zahlen in Doppelwortgröße ................     4
  136.     Testen der Bits des Flag-Registers ...................     6
  137.     Setzen eines bestimmten Bits eines Registers .........     6
  138.     Löschen eines bestimmten Bits  eines Registers .......     6
  139.     Invertieren eines bestimmten Bits eines Registers ....     6
  140.     Simulation von nicht implementierten 
  141.     Maschinenbefehlen ....................................     7
  142.     Arbeiten mit Booleschen Werten .......................     9
  143.     Ausführen von BIOS-Interrupts ........................    10
  144.     Ermittlung des Tastaturcodes einer Taste .............    10
  145.     Zeichen an den Drucker senden ........................    10
  146.     Zeichenkette an den Drucker senden ...................    10
  147.     Ausführen von Funktionen des DOS-Interrupt 21h .......    11
  148.     Belegung eines Extra-Speicherbereichs für Daten über 
  149.     DOS ..................................................    11
  150.     Freigeben von Speicherblöcken ........................    11
  151.     Ermitteln von Disketten/Platten-Werten ...............    11
  152.     Ermitteln der freien Diskkapazität ...................    12
  153.     Ermitteln der maximalen Diskkapazität ................    12
  154.     Einrichten eines neuen Directorys ....................    13
  155.     Löschen eines Directorys .............................    13
  156.     Wechseln des aktuellen Directorys ....................    13
  157.     Löschen einer Datei ..................................    13
  158.     Testen, ob eine Datei existiert ......................    13
  159.     DOS-Speicherstrukturen anschauen oder ändern .........    14
  160.     Durchlaufen der DPB-Kette (DOS 3.xx) .................    14
  161.     Benutzung der SDL ....................................    15
  162.     Ermitteln der Anzahl der Einträge in der SDL .........    17
  163.     Manipulieren der SDL .................................    17
  164.     Durchlaufen der Kette der Puffer (nur DOS 3.xx) ......    19
  165.     Ermitteln  der  Anzahl  vorhandener  Puffer ..........    19
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.     ────────────────────────────────────────────────────────────────────────────────
  180.     Inhalts-Verzeichnis                                                     I    1
  181.  
  182.  
  183.  
  184.  
  185.     Inhalt                                                 Seite
  186.     ────────────────────────────────────────────────────────────
  187.  
  188.  
  189.     Ermitteln des Wertes von LASTDRIVE ...................    20
  190.     Durchlaufen der Kette der Device-Treiber .............    21
  191.     Suchen des Device-Treibers für 'LPT1' ................    21
  192.     Ermitteln aller freien Speicherblöcke ................    22
  193.     Durchlaufen der MCB-Kette ............................    22
  194.     Benutzung von MDEBUG für das Debuggen von eigenen 
  195.     Programmen ...........................................    25
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.     ────────────────────────────────────────────────────────────────────────────────
  240.     Inhalts-Verzeichnis                                                     I    2
  241.  
  242.  
  243.  
  244.     Einleitung
  245.     ──────────
  246.  
  247.     Diese Datei  enthält Hinweise und Beispiele für  die Benutzung  von
  248.     MDEBUG.  Hauptsächlich  wird  hier auf  die  Programmiersprache des
  249.     Interpreters eingegangen.
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.  
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.     ────────────────────────────────────────────────────────────────────────────────
  300.                                                                         Seite    1
  301.  
  302.  
  303.  
  304.     Verwendete Syntax in den Beispielen
  305.     ───────────────────────────────────
  306.  
  307.     ALLE in den Beispielen  angegebenen  Werte  ohne Angabe des Formats
  308.     sind hexadezimale Werte.
  309.  
  310.     Alle Beispiele gehen davon aus, daß  die  Monitor-Start-Adresse aus
  311.     den Registern  SE und OF ermittelt wird.
  312.     Das Zeichen '@' leitet Kommentare ein.
  313.  
  314.     Hinweis:
  315.  
  316.     Bei  der Entwicklung  von Befehlsketten  die über  den H-  oder HN-
  317.     Befehl mehrfach ausgeführt  werden sollen, ist  es sinnvoll den  H-
  318.     Befehl  zuerst durch einen  W-Befehl zu  ersetzen und erst nach dem
  319.     Test den H- bzw. HN-Befehl einzusetzen.
  320.  
  321.  
  322.     Allgemeine Hinweise zur Benutzung
  323.     ─────────────────────────────────
  324.  
  325.     MDEBUG wurde nach der Philosophie
  326.  
  327.          "Alles was machbar ist, ist erlaubt."
  328.  
  329.     geschrieben. Der Anwender ist also für die Folgen  seines  Handelns
  330.     voll verantwortlich! MDEBUG selbst überprüft jeweils  nur teilweise
  331.     die Syntax der Befehle.  Mensch sollte sich also vor jeder Befehls-
  332.     Ausführung genau überlegen, was passieren kann!
  333.     Zu beachten ist auch, daß alle Speicher-Operationen mit Wort-Größen
  334.     im INTEL-Format (= Vertauschte Bytes) durchgeführt werden.
  335.  
  336.     Die Vorzüge  der Philosophie  des  Programmes  überwiegen  aber die
  337.     Nachteile bei falscher Benutzung, denke ich.
  338.  
  339.  
  340.  
  341.     Tips für die Benutzung von MDEBUG
  342.     ─────────────────────────────────
  343.  
  344.     Fast alle Befehle sind mit allen Registern möglich. Es  können also
  345.     auch Befehle, die  der  Prozessor  normalerweise  nicht  beherrscht
  346.     (z.B. das Rechnen mit Segment-Registern) ausgeführt werden.
  347.  
  348.     Zuweisungen der  Form MOV [mem1],[mem2] sind ebenfalls möglich.
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.  
  357.  
  358.  
  359.     ────────────────────────────────────────────────────────────────────────────────
  360.                                                                         Seite    2
  361.  
  362.  
  363.  
  364.     Einzelne  Werte  können  auch  in  den  Hilfsregistern  gespeichert
  365.     werden;  kleinere  Texte  oder  mehrere  Werte können im nicht mehr
  366.     benötigtem PSP von MDEBUG zwischen CS:000h und CS:0100h gespeichert
  367.     werden. (siehe auch 'Programm-Interna')
  368.  
  369.     Das PSP von  MDEBUG (oder jeder beliebige andere Speicherbereich)
  370.     kann auch zum Zwischenspeichern von Befehlen genutzt werden.
  371.  
  372.     Durch die Parameter '&name' und '*name' können im  PSP gespeicherte
  373.     Befehlszeilen oder Daten  auch in einer Datei gesichert werden bzw.
  374.     aus einer Datei restauriert werden.
  375.  
  376.     Über  die '#26'-  und  '#27'-Befehle  kann  der  Eingabepuffer  des
  377.     Interpreters  auch zum Editieren und Verändern eines  Strings (z.B.
  378.     aus dem Environment) benutzt werden.
  379.  
  380.     Über den '#27'H-Befehl können auch  mehr Befehle  als in eine Zeile
  381.     passen  auf einmal  bearbeitet  werden. Der W-Befehl, der H-Befehl,
  382.     der '#27'H-Befehl, der  ¿-Befehl  und  der ¿H-Befehl ermöglichen es
  383.     zudem kleinere 'Routinen' auszuführen.
  384.  
  385.     Mit  dem Programm  MDMKHLP.COM können  eigene  Hilfstextdateien für
  386.     die Online-Hilfe von MDEBUG erstellt werden.
  387.     (z.B.  mit  einem  Hilfstext  über  die  Datenstrukturen  eines  zu
  388.      untersuchenden  Programmes, oder aus einem Teil der .LST-Datei des
  389.      Assemblers)
  390.  
  391.     Alle  Maschinen-Befehle  können über den B- bzw. G-Befehl jederzeit
  392.     ausgeführt werden.  Der jeweilige Maschinen-Code kann z.B aus einer
  393.     .LST-Datei eines Assemblers ermittelt werden.
  394.  
  395.     Sinnvollerweise  schreibt mensch den Code für  den G-Befehl  vorher
  396.     mit  einen  normalen Assembler, übersetzt  diesen und  benutzt  das
  397.     Listing später zur Eingabe. Bzw. erstellt eine Datei der Maschinen-
  398.     codes als B-Befehl  die  dann  über  den  Parameter  '&name' in das
  399.     das PSP von MDEBUG eingelesen werden kann.
  400.  
  401.     Kleinere Routinen können auch in  übersetzter  Form  über den Para-
  402.     meter '&name' mit dem  Schalter ',N'  in das PSP eingelesen werden.
  403.     Dort  können  sie  über  den  G-Befehl  ausgeführt  werden.  Die so
  404.     geladenen Routinen dürfen aber nicht mit einem RET-Befehl enden!
  405.  
  406.  
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.     ────────────────────────────────────────────────────────────────────────────────
  420.                                                                         Seite    3
  421.  
  422.  
  423.  
  424.     Beispiele für die Interpreter-Befehle
  425.     ─────────────────────────────────────
  426.  
  427.  
  428.     Normalisieren einer Adresse
  429.  
  430.     Normalisieren  der Adresse in den Registern SE:OF. Nach der  Norma-
  431.     lisierung  hat  das Register OF nur noch einen Wert zwischen 0h und
  432.     0Fh.
  433.  
  434.          ADD SE,(OF » 4) ^ & OF,0F
  435.  
  436.  
  437.     Rechnen mit Zahlen in Doppelwortgröße
  438.     (hier in den Registern DX:AX)
  439.  
  440.  
  441.     ■ Addition
  442.  
  443.          ADD AX,2000 ^ ADD DX,FL%0      @ DX:AX <- DX:AX + 2000
  444.          oder
  445.          ADD AX,2000 ^ adc DX,0
  446.  
  447.       Falls nach der ersten Addition das Carryflag gesetzt ist, ist ein
  448.       Übertrag  vorhanden der auf das Highword (Register DX) aufaddiert
  449.       werden muß (zweiter ADD-Befehl bzw. adc-Befehl).
  450.  
  451.  
  452.     ■ Subtraktion
  453.  
  454.          SUB AX,2000 ^ SUB DX,FL%0      @ DX:AX <- DX:AX - 2000
  455.          oder
  456.          SUB AX,2000 ^ sbb DX,0
  457.  
  458.       Falls  nach der  ersten Subtraktion  das  Carryflag  gesetzt ist,
  459.       wurde noch eine  Stelle geborgt,  die von Highword  (Register DX)
  460.       abezogen werden  muß (zweiter SUB-Befehl bzw. sbb-Befehl)
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.     ────────────────────────────────────────────────────────────────────────────────
  480.                                                                         Seite    4
  481.  
  482.  
  483.  
  484.     ■ Multiplikationen bzw. Divisionen  durch eine  Zweierpotenz können
  485.       folgendermaßen programmiert werden:
  486.  
  487.       Im Beispiel wird in CL jeweils die Zweierpotenz durch die geteilt
  488.       teilt bzw. multipliziert wird gespeichert.
  489.  
  490.          MOV CL,3                       @ Multiplikant = 2^3 = 8
  491.          < DX ^ < AX ^ ADD DX,FL%0 ^ - CL ^ ¿ CL ^ H
  492.                                         @ DX:AX <- DX:AX * 8
  493.  
  494.          MOV CL,2                       @ Divisor = 2^2 = 4
  495.          > AX ^ > DX ^ ADD AX,(FL%0 * 8000) ^ - CL ^ ¿ CL ^ H
  496.                                         @ DX:AX <- DX:AX / 4
  497.  
  498.  
  499.     ■ Multiplikationen bzw. Divisionen durch  eine andere Größe  müssen
  500.       über  den  B-Befehl  durchgeführt werden, wobei in den Beispielen
  501.       davon ausgegangen wird, daß  diese Größe im Register CX steht.
  502.  
  503.       Achtung:
  504.  
  505.       Hier darf auf keinen Fall durch 0 geteilt werden! Bei verketteten
  506.       Befehlen sollte dies durch den Befehl '¿ CX' vor dem Divisionsbe-
  507.       fehl (mit dem Register durch das geteilt wird) verhindert werden.
  508.  
  509.       ■ Division
  510.  
  511.          ¿ CX ^ B F7,F1    @ AX <- (DX:AX DIV CX) und
  512.                            @ DX <- (DX:AX MOD CX)
  513.  
  514.  
  515.       ■ Multiplikation
  516.  
  517.          B F7,E1    @ DX:AX <- AX * CX
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.     ────────────────────────────────────────────────────────────────────────────────
  540.                                                                         Seite    5
  541.  
  542.  
  543.  
  544.     Testen der Bits des Flag-Registers
  545.  
  546.     ┌──────┬────────────────┬─────────────────────────────────────────┐
  547.     │      │                │             Test auf                    │
  548.     │ Bit  │ Flag           │ gesetztes Flag    nicht gesetztes Flag  │
  549.     ╞══════╪════════════════╪═════════════════╤═══════════════════════╡
  550.     │ 00h  │ Carry          │     ¿ =(FL%0)   │     ¿ (FL%0)          │
  551.     │ 01h  │ -              │                 │                       │
  552.     │ 02h  │ Parity (Even)  │     ¿ =(FL%2)   │     ¿ (FL%2)          │
  553.     │ 03h  │ -              │                 │                       │
  554.     │ 04h  │ Auxiliary      │     ¿ =(FL%4)   │     ¿ (FL%4)          │
  555.     │ 05h  │ -              │                 │                       │
  556.     │ 06h  │ Zero           │     ¿ =(FL%6)   │     ¿ (FL%6)          │
  557.     │ 07h  │ Sign           │     ¿ =(FL%7)   │     ¿ (FL%7)          │
  558.     │ 08h  │ Trap           │     ¿ =(FL%8)   │     ¿ (FL%8)          │
  559.     │ 09h  │ Interrupt      │     ¿ =(FL%9)   │     ¿ (FL%9)          │
  560.     │ 0Ah  │ Direction      │     ¿ =(FL%0A)  │     ¿ (FL%0A)         │
  561.     │ 0Bh  │ Overflow       │     ¿ =(FL%0B)  │     ¿ (FL%0B)         │
  562.     │ 0Ch  │ -              │                 │                       │
  563.     │ 0Dh  │ -              │                 │                       │
  564.     │ 0Eh  │ -              │                 │                       │
  565.     │ 0Fh  │ -              │                 │                       │
  566.     └──────┴────────────────┴─────────────────┴───────────────────────┘
  567.  
  568.     Da die unbenutzen  Bits im Flag-Register vom Prozessor immer wieder
  569.     auf eins gesetzt werden, können sie  leider nicht für eigene Zwecke
  570.     benutzt werden. Es kann aber ein  Hilfsregister oder eine Speicher-
  571.     stelle  als weiteres Flagregister benutzt werden, da der Test eines
  572.     Bits natürlich  auch mit diesen möglich ist.
  573.  
  574.  
  575.     Setzen eines bestimmten Bits eines Registers
  576.  
  577.          | AX,1«4                       @ Setze Bit 4 von AX
  578.  
  579.  
  580.     Löschen eines bestimmten Bits  eines Registers
  581.  
  582.          & AX,(1«3)!-1                  @ Lösche Bit 3 von AX
  583.  
  584.  
  585.     Invertieren eines bestimmten Bits eines Registers
  586.  
  587.          ! AX,1«7                       @ Invertiere Bit 7 von AX
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.     ────────────────────────────────────────────────────────────────────────────────
  600.                                                                         Seite    6
  601.  
  602.  
  603.  
  604.     Simulation von nicht implementierten Maschinenbefehlen
  605.  
  606.     ■ Simulation von REPNE SCASB
  607.  
  608.       Damit AL durch die Subtraktion  nicht  verändert wird,  wird hier
  609.       als  erster  Operand  ein Ausdruck, dessen Wert gleich dem Inhalt
  610.       von AL ist,  verwendet.  Die Subtraktion  verändert daher nur die
  611.       Flags  (Benutzung des Pseudo-Registers). Da der erste Operand ein
  612.       Ausdruck ist (= Wort!), muß bei der Speicheradresse explizit  das
  613.       Byte-Format  angegeben  werden.  ES:DI  zeigt nach der Ausführung
  614.       entweder auf  das gefundene Zeichen oder  auf das  erste  Zeichen
  615.       hinter  dem String. (je nach Cursor-Position)
  616.  
  617.          S AL+0,ES:*DI ^ ¿ 1-FL%6      ^ + DI   ^ - CX  ^ ¿ CX ^ H
  618.          ─────────────   ────────        ────     ─────   ────   ─
  619.          Vergleich      Wert gefunden?  Zeiger   Zähler  CX=0? Schleife
  620.                         (ZF = 1)        erhöhen  korrig.       zuende?
  621.  
  622.     ■ Simulation von REPE SCASW
  623.  
  624.          S AX+0,ES:DI ^ ¿ FL%6 ^ ADD DI,2 ^ - CX ^ ¿ CX ^ H
  625.  
  626.     ■ Simulation des Befehls CMP AX,BX
  627.  
  628.       Damit  AX  nicht  verändert  wird,  wird hier wieder  das Pseudo-
  629.       Register benutzt, d.h. nach dem  Befehl  sind wie  beim Original-
  630.       Befehl nur die Flags verändert.
  631.  
  632.          S AX+0,BX
  633.  
  634.     ■ Simulation der Befehle SAHF und LAHF
  635.  
  636.       Diese Befehle können  nicht direkt  simuliert  werden, allerdings
  637.       kann der Wert des Flag-Registers durch einen einfachen MOV-Befehl
  638.       in ein anderes Register gesichert bzw. aus einem anderen Register
  639.       restauriert werden.
  640.  
  641.          MOV AX,FL             @ Save Flags in AX   (SAHF)
  642.          MOV FL,AX             @ Load Flags from AX (LAHF)
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.     ────────────────────────────────────────────────────────────────────────────────
  660.                                                                         Seite    7
  661.  
  662.  
  663.  
  664.     ■ Simulation des Befehls LDS SI,BX
  665.  
  666.          MOV SI,DS:[BX] ^ MOV DS,DS:[BX+2]
  667.  
  668.     ■ Simulation des Befehls ROL AX,1
  669.  
  670.          < AX ^ | AX,FL%0
  671.  
  672.     ■ Simulation des Befehls ROR AX,1
  673.  
  674.          > AX ^ | AX,FL%0*8000
  675.  
  676.     ■ Simulation des Befehls XCHG AX,BX
  677.  
  678.          ! AX,BX ^ ! BX,AX ^ ! AX,BX
  679.  
  680.     ■ Simulation des Befehls XLATB
  681.  
  682.          MOV AL,DS:[BX+AL]
  683.  
  684.     ■ Simulation der FOR-Schleife 'FOR CX=4 TO 9 BY 1 DO { AL = AL+5 }'
  685.  
  686.          Vorbereitung:
  687.  
  688.          MOV CX,4              @ Anfangswert ins Zählregister
  689.  
  690.          Ausführung:
  691.  
  692.          Im  Beispiel  wird nur AX jeweils um 5 erhöht. Der Endwert für
  693.          die Schleife ist hier 9, die Schleife soll  6 mal (9 - 4 + 1 )
  694.          durchlaufen werden.
  695.  
  696.          ADD AL,5 ^ + CX ^ ¿ CX<(9+1) ^ H
  697.                            ──────────
  698.                            Ausführen solange CX kleiner als der
  699.                            Endwert+1 ist
  700.  
  701.     ■ Simulation der WHILE-Schleife 'WHILE (AL <> 0) DO { INC AX }'
  702.  
  703.          ¿ AL¬0 ^ + AX ^ H
  704.  
  705.     ■ Simulation der UNTIL-Schleife 'REPEAT { INC AX } UNTIL (AL = 0)'
  706.  
  707.          + AX ^ ¿ AL¬0 ^ H
  708.          oder
  709.          + AX ^ ¿H AL=0
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.     ────────────────────────────────────────────────────────────────────────────────
  720.                                                                         Seite    8
  721.  
  722.  
  723.  
  724.     Arbeiten mit Booleschen Werten
  725.  
  726.     Die  Operatoren  '=', '<', '>',  '¬' und '%' ergeben  alle entweder
  727.     1 (= TRUE)  oder 0 (= FALSE).  Da  der ¿-  und der  ¿H-Befehl einen
  728.     Booleschen Wert testen, können hiermit auch logische  Verknüpfungen
  729.     programmiert werden.  Es sollte  allerdings darauf geachtet werden,
  730.     daß keinerlei  Operator-Prioritäten vorhanden sind. (Alle Beispiele
  731.     ohne explizite Angabe gehen von  vorzeichenlosen Werten aus.)
  732.  
  733.          ¿ AX=BX                    @ Bearbeitung fortsetzen,
  734.                                     @ falls AX = BX
  735.  
  736.          ¿ ((AX < BX) | (AX > BX))  @ Bearbeitung fortsetzen,
  737.                                     @ falls AX <> BX
  738.                                     @ (Simulation des Operators '¬')
  739.  
  740.          ¿ ((AX < BX) | (AX = BX))  @ '<='-Operator
  741.  
  742.          ¿ ( (AX < 8) & (AX > 1) )  @ Bearbeitung fortsetzen, falls AX
  743.                                     @ im Intervall 2 bis 7 (incl.) liegt
  744.  
  745.          ¿ ( (AX < 2) | (AX > 8) )  @ Bearbeitung fortsetzen, falls AX
  746.                                     @ nicht im Intervall 2 bis 8
  747.                                     @ (incl.) liegt
  748.  
  749.          ¿ ( AX%0 = 0 )             @ Bearbeitung fortsetzen, falls der
  750.                                     @ Wert aus AX gerade ist,  d.h. das
  751.                                     @ 0-te Bit ist nicht gesetzt
  752.  
  753.          ¿ ( AX%0F = 0)             @ Bearbeitung fortsetzen, falls der
  754.                                     @ vorzeichenbehaftete  Wert  aus AX
  755.                                     @ größer oder gleich 0 ist, d.h. das
  756.                                     @ 15-te Bit ist nicht gesetzt
  757.  
  758.          ¿ ( (DX > CX) | ( (AX > BX) & (DX = CX) ) )
  759.                                     @ Bearbeitung fortsetzen, falls das
  760.                                     @ Doppelwort in DX:AX größer als
  761.                                     @ das Doppelwort in CX:BX ist
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.     ────────────────────────────────────────────────────────────────────────────────
  780.                                                                         Seite    9
  781.  
  782.  
  783.  
  784.     Ausführen von BIOS-Interrupts
  785.  
  786.     Über den  INT-Befehl kann  jederzeit jeder beliebige BIOS-Interrupt
  787.     aufgerufen werden. Beachtet werden muß aber, daß verschiedene BIOS-
  788.     Routinen (z.B. des Interrupt 13h) NICHT reentrant sind!
  789.  
  790.  
  791.     Ermittlung des Tastaturcodes einer Taste
  792.  
  793.          MOV AH,0 ^ INT 16     @ Funktion 0 des INT 16h ->> Taste lesen
  794.                                @ entsprechende Taste drücken
  795.  
  796.     AX enthält nun den vom Interrupt 16h gelieferten Tastatur-Code
  797.  
  798.  
  799.     Zeichen an den Drucker senden
  800.  
  801.          MOV AL,'<zeichen>'    @ AL mit dem zu sendenden Zeichen laden
  802.          MOV AH,0              @ AH mit der Funktions-Nummer laden
  803.          MOV DX,0              @ DX mit der Drucker-Nummer laden
  804.                                @ (lpt1 = 0, lpt2 = 1, usw.)
  805.          INT 17                @ Drucker-Interrupt ausführen
  806.                                @ AH enthält nun den Druckerstatus
  807.  
  808.  
  809.     Zeichenkette an den Drucker senden
  810.  
  811.          Vorbereitung:
  812.  
  813.          In  einen freien  Speicherbereich die  gewünschte Zeichenkette
  814.          abgeschlossen mit einem Endemarker (hier  ein Null-Byte)  ein-
  815.          tragen und DS:BX auf die Adresse der Kette setzen.
  816.          (Ausgabe auf LPT1)
  817.  
  818.          Ausführung:
  819.  
  820.          M AL,DS:[BX] ^ ¿ AL¬0   ^ + BX ^ M AH,0 ^ M DX,0 ^ I 17 ^ H
  821.          ────────────   ──────     ──────────────────────   ────
  822.          akt. Zeichen    Ketten-    Zeiger korrigieren und   Zeichen
  823.          nach AL         Ende ?     Register laden           drucken
  824.  
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.     ────────────────────────────────────────────────────────────────────────────────
  840.                                                                         Seite   10
  841.  
  842.  
  843.  
  844.     Ausführen von Funktionen des DOS-Interrupt 21h
  845.  
  846.     Prinzipiell können aus MDEBUG heraus auch alle  Funktionen des DOS-
  847.     Interrupts 21h ausgeführt  werden.  Da  die meisten  Funktionen des
  848.     Interrupt  21h  NICHT  reentrant sind,  sollten  Funktionen  dieses
  849.     Interrupts aber nur  ausgeführt  werden,  falls das (DOS-)Busy-Flag
  850.     von MDEBUG auf 0 steht.  Ansonsten  ist ein  Systemabsturz nach dem
  851.     Ende des Aufrufs von MDEBUG sehr wahrscheinlich!
  852.  
  853.  
  854.     Belegung eines Extra-Speicherbereichs für Daten über DOS
  855.  
  856.          MOV BX,0010 ^ MOV AH,48 ^ INT 21
  857.                                @ BX = Größe  des Speicherbereichs in
  858.                                @ Paragraphen á 16 Byte; die Gesamtgröße
  859.                                @ des zu belegenden Speichers  ist  also
  860.                                @ 16*10h (= 16 dez) = 256 Byte (dez.)
  861.  
  862.     Falls das Carry-Flag gelöscht ist, enthält  AX nun das Segment  des
  863.     belegten  Speicherbereichs,  andernfalls enthält BX  die Größe  des
  864.     größten  freien  Speicherbereichs in  Paragraphen. Die  Adresse aus
  865.     AX muß  im  Erfolgsfall (z.B.) in einem  Hilfsregister  gespeichert
  866.     werden, da dieser Speicherbereich vor dem Entfernen  von MDEBUG aus
  867.     dem Speicher wieder  freigegeben werden  sollte. Nach diesem Befehl
  868.     muß der Besitzer im  neuen MCB (Segment = AX-1, Besitzer = Wort  am
  869.     Offset 1) korrigiert werden (z.B. PSP von MDEBUG eintragen).
  870.  
  871.  
  872.     Freigeben von Speicherblöcken
  873.  
  874.          MOV ES,freizugebendes_Segment ^ MOV AH,49 ^ INT 21
  875.  
  876.  
  877.     Ermitteln von Disketten/Platten-Werten
  878.  
  879.     Hinweis:
  880.  
  881.     Falls die Werte einer Diskette ermittelt werden sollen, sollte auch
  882.     eine  Diskette  im geschlossenen Diskettenlaufwerk sein (sonst wird
  883.     der Interrupt 24h aufgerufen)!
  884.                  
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.     ────────────────────────────────────────────────────────────────────────────────
  900.                                                                         Seite   11
  901.  
  902.  
  903.  
  904.     Ermitteln der freien Diskkapazität
  905.  
  906.          MOV AH,36 ^ MOV DL,0 ^ INT 21
  907.                              @ DL = Laufwerknummer, 0 = akt. LW,
  908.                              @ 1 = Lw. A, 2 = Lw B, etc.
  909.  
  910.     Falls AX = 0FFFF wurde  eine unbekannte  Laufwerksnummer angegeben.
  911.     Sonst kann die freie Diskkapazität ermittelt werden durch:
  912.  
  913.          MOV DX,0
  914.          B F7,E1             @ MUL CX
  915.          B F7,E3             @ MUL BX
  916.                              @ DX:AX enthält die freie Kapazität
  917.                              @ in Bytes (als Doppelwort)
  918.  
  919.  
  920.     Ermitteln der maximalen Diskkapazität
  921.  
  922.          MOV AH,36 ^ MOV DL,0 ^ INT 21
  923.                              @ DL =Laufwerknummer, 0 = akt. LW,
  924.                              @ 1 = Lw. A, 2 = Lw B, etc.
  925.  
  926.     Falls AX = 0FFFF wurde eine unbekannte Laufwerksnummer angegegeben.
  927.     Sonst kann die Diskkapazität ermittelt werden durch:
  928.  
  929.          MOV BX,DX           @ Anzahl Cluster nach BX
  930.          B F7,E1             @ MUL CX -> DX:AX = Bytes/Cluster
  931.          B F7,E3             @ MUL BX -> DX:AX enthält nun die max.
  932.                              @ Kapazität in Bytes (als Doppelwort)
  933.  
  934.     Sinnvollerweise  teilt mensch den erhaltenen Wert durch 1024 um den
  935.     Wert in KB zu erhalten und  somit  in einem  Register darstellen zu
  936.     können:
  937.  
  938.          MOV BX,#1024 ^ B F7,F3   @ DIV BX (=1024)
  939.          MOV R8,AX                @ R8 = max. Diskkapazität in KB
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.     ────────────────────────────────────────────────────────────────────────────────
  960.                                                                         Seite   12
  961.  
  962.  
  963.  
  964.     Falls  die im Kommandotreiber MDBSPDRV.COM  implementierten Befehle
  965.     zur  Datei- und Directorybehandlung nicht angewendet werden können,
  966.     können diese folgendermaßen programmiert werden:
  967.  
  968.     Für alle folgenden Beispiele auf dieser Seite gilt:
  969.  
  970.     Vor der Ausführung der Befehle muß der Name des Directorys bzw. der
  971.     Datei abgeschlossen mit einem Null-Byte in einem freien Speicherbe-
  972.     reich eingetragen werden.Die Adresse des Namens muß in die Register
  973.     DS (Segment) und DX (Offset) eingetragen werden.
  974.  
  975.     Falls  nach der  Ausführung das  Carry-Flag  gelöscht  ist, war die
  976.     Aktion erfolgreich.
  977.     Andernfalls trat  ein Fehler  auf und  das Register  AX enthält die
  978.     DOS-Fehlernummer.
  979.  
  980.  
  981.     Einrichten eines neuen Directorys
  982.  
  983.          MOV AH,39 ^ INT 21
  984.  
  985.  
  986.     Löschen eines Directorys
  987.  
  988.          MOV AH,3A ^ INT 021
  989.  
  990.  
  991.     Wechseln des aktuellen Directorys
  992.  
  993.          MOV AH,3B ^ INT 021
  994.  
  995.  
  996.     Löschen einer Datei
  997.  
  998.          MOV AH,41 ^ INT 021
  999.  
  1000.  
  1001.     Testen, ob eine Datei existiert
  1002.  
  1003.          MOV AX,4300 ^ INT 021          @ CF = 0 ->> CX = Dateiattribut
  1004.  
  1005.  
  1006.  
  1007.  
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.     ────────────────────────────────────────────────────────────────────────────────
  1020.                                                                         Seite   13
  1021.  
  1022.  
  1023.  
  1024.     DOS-Speicherstrukturen anschauen oder ändern
  1025.  
  1026.  
  1027.     Durchlaufen der DPB-Kette (DOS 3.xx)
  1028.  
  1029.     Im Interpeter durch den Befehl
  1030.  
  1031.          D M3
  1032.  
  1033.     die Monitor-Start-Adresse  ändern. Der Monitor zeigt nun den ersten
  1034.     DPB an. Da das Verkettungs-Feld der DPBs nicht am Offset 0h sondern
  1035.     beim  Offset  18h  beginnt, wird  für das Durchlaufen der  DPBs ein
  1036.     verketteter Befehl oder ein Ausdruck benötigt:
  1037.  
  1038.          ADD OF,18 ^ P OF
  1039.     oder:
  1040.          P [OF+18]
  1041.  
  1042.     Durch Betätigen von  <CTRL-RETURN>  kann  jetzt  im Interpreter die
  1043.     Kette der DPBs durchlaufen werden.
  1044.  
  1045.     Unter Zuhilfename des W-Befehls lautet die Befehlszeile:
  1046.  
  1047.          ADD OF,18 ^ P OF ^ W
  1048.     oder:
  1049.          P [OF+18] ^ MOV BX,[OF+18] ^ ¿ (BX+1)  ^ W
  1050.  
  1051.     Durch die Eingabe von <Backspace> auf dem W-Befehl wird jeweils der
  1052.     nächste DPB angezeigt.
  1053.  
  1054.     Hinweis:
  1055.     Der  letzte DPB hat als Offset im  Verkettungsfeld  beim Offset 18h
  1056.     den Wert 0FFFFh stehen. Deshalb beendet (0FFFFh = -1 -> -1 + 1 = 0)
  1057.     die Ausführung.
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.     ────────────────────────────────────────────────────────────────────────────────
  1080.                                                                         Seite   14
  1081.  
  1082.  
  1083.  
  1084.     Benutzung der SDL
  1085.  
  1086.     ■ Ermittlung der  Datei bzw.  des Geräts dem ein Handle  zugeordnet
  1087.       ist über die SDL.
  1088.  
  1089.     Zuerst muß über die Befehle
  1090.  
  1091.          MOV AH,062 ^ I 21 ^ MOV SE,BX ^ MOV OF,0
  1092.  
  1093.     das aktuelle PSP im Monitor angezeigt werden. Da diese Funktion des
  1094.     Interrupts 21h reentrant ist, kann sie jederzeit ausgeführt werden.
  1095.     Danach wird durch die Befehle
  1096.  
  1097.          MOV CX,[OF+32] ^ P OF+34
  1098.  
  1099.     das Register CX mit  der maximal  möglichen  Anzahl Handles geladen
  1100.     und die akt. lokale  Handle-Tabelle im Monitor angezeigt. Falls der
  1101.     Wert  im Register CX kleiner  als das zu  untersuchende Handle ist,
  1102.     ist dieses nicht bekannt (d.h. für den akt. Prozess unbelegt).
  1103.     Ansonsten kann jetzt über den Befehl
  1104.  
  1105.          MOV BL,[OF+HandleNummer] ^ MOV BH,0
  1106.  
  1107.     das gewünschte Handle in das DOS-interne Handle konvertiert werden.
  1108.     Falls dabei für BX der Wert  00FFh  herauskommt, ist das angegebene
  1109.     Handle für den akt. Prozess noch nicht belegt.
  1110.     Andernfalls kann danach über den Befehl
  1111.  
  1112.          D M4 ^ MOV CX,[OF+04]
  1113.  
  1114.     die erste  Teilliste der SDL  im Monitor  angezeigt und  CX mit der
  1115.     Anzahl  Elemente in dieser Teilliste geladen werden.
  1116.     Jetzt  muß  überprüft  werden, ob  der Wert in CX  größer  als  das
  1117.     ermittelte  DOS-interne  Handle ist oder nicht. Falls dies der Fall
  1118.     ist, muß  zuerst über den Befehl
  1119.  
  1120.          P OF
  1121.  
  1122.     die zweite Teilliste der SDL im Monitor angzeigt werden. (Ansonsten
  1123.     kann dieser Befehl entfallen)
  1124.  
  1125.     Durch den Befehl
  1126.  
  1127.          ADD OF,6
  1128.  
  1129.     muß nun der Header der Teilliste der SDL überlesen werden und durch
  1130.     den Befehl
  1131.  
  1132.          ADD OF,(BX*#53)+20         @ DOS 3.xx
  1133.     bzw.
  1134.          ADD OF,(BX*#59)+20         @ DOS 4.+
  1135.  
  1136.     wird im Monitor beim Offset SE:OF der Name des zugeordneten Gerätes
  1137.     bzw. der zugeordneten Datei angezeigt.
  1138.  
  1139.     ────────────────────────────────────────────────────────────────────────────────
  1140.                                                                         Seite   15
  1141.  
  1142.  
  1143.  
  1144.     Graphisch dargestellt sieht das Ganze dann folgendermaßen aus:
  1145.  
  1146.            Interrupt 21h mit AH = 62h  -> Ausgabe: BX = Zeiger auf akt.
  1147.                                                    ║    PSP (Segment=BX,
  1148.         ╔══════════════════════════════════════════╝         Offset=0)
  1149.         ║                    ┌──  Länge der lokalen Handle-Tabelle
  1150.         ║                    │           ┌── Adresse der lokalen Handle-
  1151.         ║                    │           │                       Tabelle
  1152.         ║                Offset 32h  Offset 34h
  1153.         ║  ┌────┬────┬─────┬──────┬───────────┬───┐
  1154.         ╚═>│ CD │ 20 │ ... │ mmmm │  seg:off  │...│ akt. PSP des Programms
  1155.            └────┴────┴─────┴──────┴───────────┴───┘
  1156.                                         ║
  1157.      ╔══════════════════════════════════╝
  1158.      ║┌─ Rückgabe der Routinen zur Dateiverarbeitung (Eröffnung) mit Handles
  1159.      ║│             ┌──> Handle für Routinen zur Dateiverarbeitung mit Handles
  1160.      ║│             │
  1161.      ║└> Index: >───┘  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 10 11 12 13
  1162.      ║ Inhalt z.B.:  ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐
  1163.      ╚══════════════>│01│01│01│00│02│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│-1│
  1164.                   ┌─<└──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┴──┘
  1165.                   │   ^  ^  ^  ^  ^  ^ ...
  1166.                   │   │  │  │  │  │  └ Ab hier folgen die Handle
  1167.                   │   │  │  │  │  │    für Benutzer-Definierte Dateien
  1168.                   │   └──┴──┴──┴──┴─ vordefinierte Handles
  1169.     ┌─────────────┘
  1170.     └────> Der Eintrag des Tabellen-Elementes mit dem gewünschten Index
  1171.            wird nun als Index für die System-Datei-Liste (SDL) genommen
  1172.            in  deren  Einträgen  jeweils beim  Offset 20h der  Name des
  1173.            Gerätes bzw. der Datei steht.
  1174.  
  1175.          1. Teilliste der SDL
  1176.        ┌───────────────────────────────────────────────────────────┐
  1177.        │ Zeiger auf die 2. Teilliste des SDL                       │══╗
  1178.        ├───────────────────────────────────────────────────────────┤  ║
  1179.        │ Anzahl Einträge in dieser Teilliste (normalerweise 5)     │  ║
  1180.        ├───────────────────────────────────────────────────────────┤  ║
  1181.        │ 1. Eintrag in dieser Teilliste      (= 0. Eintrag gesamt) │  ║
  1182.        │ ...                                                       │  ║
  1183.        │ Letzter Eintrag in dieser Teilliste (= 4. Eintrag gesamt) │  ║
  1184.        └───────────────────────────────────────────────────────────┘  ║
  1185.     ╔═════════════════════════════════════════════════════════════════╝
  1186.     ║    2. Teilliste der SDL
  1187.     ║  ┌───────────────────────────────────────────────────────────┐
  1188.     ╚═>│ Zeiger auf die nächste Teilliste, normalerweise FFFF:FFFF │
  1189.        ├───────────────────────────────────────────────────────────┤
  1190.        │ Anzahl Einträge in dieser Teilliste (Anz.= FILES - 5)     │
  1191.        ├───────────────────────────────────────────────────────────┤
  1192.        │ 1. Eintrag in dieser Teilliste      (= 5. Eintrag gesamt) │
  1193.        │ ...                                                       │
  1194.        │ Letzter Eintrag in dieser Teilliste (= n. Eintrag gesamt  │
  1195.        │                                      mit n = FILES - 1)   │
  1196.        └───────────────────────────────────────────────────────────┘
  1197.  
  1198.  
  1199.     ────────────────────────────────────────────────────────────────────────────────
  1200.                                                                         Seite   16
  1201.  
  1202.  
  1203.  
  1204.     Ermitteln der Anzahl der Einträge in der SDL
  1205.  
  1206.     (= FILES aus der Datei CONFIG.SYS,  Vorr.:  keine individuelle Ver-
  1207.     längerung der SDL in Kraft und FILES nicht im EMS installiert)
  1208.  
  1209.          MOV CX,0 ^ D M4 ^ A CX,[OF+4] ^ P OF ^ ADD CX,[OF+4]
  1210.  
  1211.     In CX steht nun die gewünschte Anzahl.
  1212.  
  1213.  
  1214.     Manipulieren der SDL
  1215.  
  1216.     Beispiel:
  1217.  
  1218.     Nach mehreren Debugger-Sitzungen, bei  denen jeweils Dateien eröff-
  1219.     net, aber  nicht wieder  geschlossen wurden,  tritt der  DOS-Fehler
  1220.     'Kein freies Handle mehr' auf,  d.h. die SDL  enthält  keine freien
  1221.     Einträge mehr.
  1222.  
  1223.     In diesem Fall kann von versierten(!) Programmierern  mit Hilfe von
  1224.     MDEBUG die interne System-Datei-Liste korrigiert werden:
  1225.  
  1226.     Zuerst muß hierfür im Interpreter durch den Befehl
  1227.  
  1228.          D M4
  1229.  
  1230.     die erste Teilliste der SDL im Monitor angezeigt werden.
  1231.  
  1232.     Da die nun angezeigte erste Teilliste der SDL im Normalfall nur die
  1233.     Einträge für  die Systemdateien/geräte (CON, LPT1, COM1, usw.) ent-
  1234.     hält, sollten in dieser Liste keine Änderungen vorgenommen werden.
  1235.  
  1236.     Der Befehl
  1237.  
  1238.          P OF
  1239.  
  1240.     führt deshalb zur Anzeige der zweiten Teilliste der SDL.
  1241.  
  1242.     Beim Offset OF+4 steht die Anzahl der Einträge in dieser Liste (als
  1243.     Wortgröße), die  mensch sich mit dem Befehl
  1244.  
  1245.          MOV R7,[OF+4]
  1246.  
  1247.     im Register R7 merken sollte.
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.     ────────────────────────────────────────────────────────────────────────────────
  1260.                                                                         Seite   17
  1261.  
  1262.  
  1263.  
  1264.     Hinweis:
  1265.  
  1266.     Falls beim Offset OF ein Doppelwort mit Offset und Segment ungleich
  1267.     0FFFFh steht, ist dies ein Zeiger auf eine weitere Teilliste.
  1268.  
  1269.     Nun kann mit dem Befehl
  1270.  
  1271.          ADD OF,6
  1272.  
  1273.     der nicht  mehr benötigte  Header  der  Teilliste überlesen werden.
  1274.     SE:OF  zeigt nun auf den 1. Eintrag in der  Teilliste der SDL. Beim
  1275.     Offset OF+20h steht der Name der Datei (bzw. des Gerätes) der (dem)
  1276.     dieser Eintrag zugeordnet ist.
  1277.  
  1278.     Der Wert am  Offset OF bestimmt, ob der Eintrag belegt (wert <> 0 =
  1279.     Anzahl der Verweise auf diesen Eintrag) oder frei (wert=0) ist. Der
  1280.     Wert am  Offset OF+02h  bestimmt, ob  die Datei zum Lesen (wert=0),
  1281.     zum  Schreiben  (wert=1)  oder  zum  Lesen  und  Schreiben (wert=2)
  1282.     geöffnet ist.
  1283.  
  1284.     Falls  der Eintrag  nicht  mehr  benötigt  wird, kann er  durch den
  1285.     Befehl
  1286.  
  1287.          MOV [OF],0
  1288.  
  1289.     gelöscht werden.
  1290.  
  1291.     Falls mehrere Einträge gelöscht werden sollen, bietet sich folgende
  1292.     Befehlskette an:
  1293.  
  1294.          ADD OF,35 ^ - R7 ^ W ^ MOV [OF],0 ^ ¿ R7 ^ H   @ DOS 3.xx
  1295.     bzw.
  1296.          ADD OF,3B ^ - R7 ^ W ^ MOV [OF],0 ^ ¿ R7 ^ H   @ DOS 4+
  1297.  
  1298.     Zuerst  wird  der Monitor  auf  die Adresse  des  nächsten Eintrags
  1299.     gesetzt und dann über den W-Befehl angezeigt. Die Eingabe von <ESC>
  1300.     bricht  die weitere Ausführung  der Befehlszeile  nun ab,  d.h. der
  1301.     Eintrag wird NICHT gelöscht; die Eingabe von <Backspace> verhindert
  1302.     ebenfalls  die Löschung  des  Eintrags  allerdings wird sofort  der
  1303.     nächste Eintrag angezeigt. Jede andere Taste führt zur Löschung des
  1304.     Eintrages und zur Anzeige des  nächsten  Eintrages. Die SDL kann so
  1305.     bequem  durchlaufen werden, wobei das Hilfsregister  R7 als  Zähler
  1306.     dient.  Der  Befehl '¿ R7'  beendet  dann die  Ausführung  nach den
  1307.     letzten Eintrag.
  1308.     Allerdings  können  hier  durch das  Schließen von Dateien, die zum
  1309.     Schreiben auf  waren,  oder  bei geladener  Netzwerksoftware Daten-
  1310.     verluste auftreten!
  1311.  
  1312.  
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.     ────────────────────────────────────────────────────────────────────────────────
  1320.                                                                         Seite   18
  1321.  
  1322.  
  1323.  
  1324.     Durchlaufen der Kette der Puffer (nur DOS 3.xx)
  1325.  
  1326.     Im Interpreter durch den Befehl
  1327.  
  1328.          D M7
  1329.  
  1330.     den Monitor auf die Adresse des ersten Puffers in der Kette setzen.
  1331.     Danach den Interpreter durch die Taste <ESC>  verlassen. Der Cursor
  1332.     steht  jetzt  auf dem Verkettungs-Feld des ersten Puffers,  so  daß
  1333.     die Kette der  Puffer durch  Eingabe von <P> im Monitor durchlaufen
  1334.     werden kann.
  1335.  
  1336.     Im Interpreter lautet der Befehl zur Anzeige  des  jeweils nächsten
  1337.     Puffers:
  1338.  
  1339.          P OF
  1340.  
  1341.     Unter  Zuhilfenahme des W- und ¿-Befehls kann folgende Befehlskette
  1342.     benutzt werden:
  1343.  
  1344.          P OF ^ MOV BX,[OF] ^ ¿ (BX+1) ^ W
  1345.  
  1346.     Durch die Eingabe von <Backspace> auf den W-Befehl wird jeweils der
  1347.     nächste Puffer  angezeigt. Der ¿-Befehl beendet die Ausführung nach
  1348.     dem letzten Puffer, da der letzte Puffer als Offset im Verkettungs-
  1349.     Feld -1 (= 0FFFFh) stehen hat.
  1350.  
  1351.  
  1352.     Ermitteln  der  Anzahl  vorhandener  Puffer
  1353.     (= BUFFERS aus der Datei CONFIG.SYS, nur bei DOS 3.xx)
  1354.  
  1355.          Vorbereitung:
  1356.  
  1357.          D M7 ^ MOV CX,0
  1358.  
  1359.          Ausführung:
  1360.  
  1361.          + CX ^ MOV AX,[OF] ^ ¿ AX+1 ^ P OF ^ H
  1362.  
  1363.     In CX steht nun die Anzahl vorhandener Puffer.
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.     ────────────────────────────────────────────────────────────────────────────────
  1380.                                                                         Seite   19
  1381.  
  1382.  
  1383.  
  1384.     ■ Testen, ob der Sektor  003 des  Laufwerks D: in einem Puffer vor-
  1385.       liegt (nur DOS 3.xx)
  1386.  
  1387.          Vorbereitung:
  1388.          (BX = Sektornummer,
  1389.           CL = Laufwerknummer, wobei A = 0, B = 1, C = 2 usw.):
  1390.  
  1391.          D M7 ^ MOV BX,0003 ^ MOV CL,'D'-'A'
  1392.  
  1393.          Ausführung:
  1394.          (damit  die  Befehlszeile  auf einmal  eingegeben werden kann,
  1395.           sind alle unnötigen Trennzeichen weggelassen worden)
  1396.  
  1397.          M AX,[OF^¿ AX+1^M AX,[OF+6^M CH [OF+4^¿ =((AX=BX)&(CL=CH))^P OF^H
  1398.  
  1399.     SE:OF zeigt nach dem Ende der Befehlszeile entweder auf den betref-
  1400.     fenden oder den  letzten  Puffer. Der  Cursor  steht im ersten Fall
  1401.     hinter  dem  zweiten  ¿-Befehl, im  zweiten Fall  hinter dem ersten
  1402.     ¿-Befehl.
  1403.  
  1404.  
  1405.     Ermitteln des Wertes von LASTDRIVE
  1406.  
  1407.          D M0 ^ MOV 8L,[OF+29] ^ ADD 8L,'@'
  1408.  
  1409.     oder (ohne Veränderung des Monitors, DOS-Busy-Flag = 0!):
  1410.  
  1411.          MOV AH,52 ^ I 21 ^ MOV 8L,ES:[BX+21] ^ ADD 8L,'@'
  1412.  
  1413.     Das  Register  8L (= Lowbyte von R8) enthält nun den Buchstaben des
  1414.     letzten möglichen logischen Laufwerkes.
  1415.  
  1416.  
  1417.     ■ Ermitteln des physikalischen Pfades des logischen Laufwerkes O:
  1418.       (Vorr.: Der bei  LASTDRIVE in der  Datei  CONFIG.SYS angegebene
  1419.               Wert ist größer oder gleich 'O'!)
  1420.  
  1421.          D M8 ^ ADD OF,('O'-'A')*51      @ DOS 3.xx
  1422.       bzw.
  1423.          D M8 ^ ADD OF,('O'-'A')*58      @ DOS 4.+
  1424.  
  1425.     SE:OF  zeigt nun auf den physikalischen Pfad für das logische Lauf-
  1426.     werk 'O:'. Falls im Byte  mit dem Offset  OF+44 das Bit Nr. 6 nicht
  1427.     gesetzt ist, ist das Laufwerk nicht bekannt.
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.     ────────────────────────────────────────────────────────────────────────────────
  1440.                                                                         Seite   20
  1441.  
  1442.  
  1443.  
  1444.     Durchlaufen der Kette der Device-Treiber
  1445.  
  1446.          Vorbereitung:
  1447.  
  1448.          D M0 ^ A OF,2A ^ M CX,0    @ -> SE:OF zeigt auf das NUL-Device
  1449.                                     @ -> CX = Zähler für die Devices
  1450.  
  1451.          Ausführung:
  1452.  
  1453.          + CX ^ P OF ^ MOV AX,[OF] ^ ¿ AX+1 ^ W
  1454.  
  1455.     Nach Eingabe von <Backspace> auf den W-Befehl wird jeweils der Kopf
  1456.     jedes Treibers angezeigt.
  1457.     Nach  Beenden  der Befehlskette durch den ¿-Befehl zeigt  SE:OF auf
  1458.     den letzten Treiber und CX enthält die Anzahl der geladenen Treiber.
  1459.  
  1460.  
  1461.     Suchen des Device-Treibers für 'LPT1'
  1462.  
  1463.          Vorbereitung:
  1464.  
  1465.          D M0 ^ ADD OF,2A ^ MOV DX,'PL' ^ MOV CX,'1T'
  1466.                                   @ -> SE:OF zeigt auf das NUL-Device
  1467.                                   @ -> DX:CX = Suchstring
  1468.  
  1469.          Ausführung
  1470.          (der  erste  Treiber ist  immer das  NUL-Device  und kann also
  1471.           überlesen werden. Damit die  Befehlszeile auf einmal eingege-
  1472.           ben werden kann  sind alle unnötigen Trennzeichen weggelassen
  1473.           worden)
  1474.  
  1475.          P OF^M AX,[OF+A^M BX,[OF+C^¿ =((AX=DX)&(BX=CX))^M AX,[OF^¿ AX+1^H
  1476.  
  1477.     Nach Beenden der  Befehlskette durch den ¿-Befehl zeigt  SE:OF ent-
  1478.     weder auf den Treiber für 'LPT1'  oder auf den  letzten Treiber (je
  1479.     nachdem hinter welchen ¿-Befehl der Cursor steht).
  1480.  
  1481.  
  1482.  
  1483.  
  1484.  
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.     ────────────────────────────────────────────────────────────────────────────────
  1500.                                                                         Seite   21
  1501.  
  1502.  
  1503.  
  1504.     Ermitteln aller freien Speicherblöcke
  1505.  
  1506.          Vorbereitung:
  1507.  
  1508.          D M2
  1509.  
  1510.          Ausführung:
  1511.  
  1512.          M AL,[OF] ^¿ AL-'Z' ^A SE,[OF+3] ^+ SE ^M AX,[OF+1] ^¿ AX¬0 ^H
  1513.  
  1514.     Die  Ausführung  der  Befehlskette wird  bei jeden  Erreichen eines
  1515.     freien Speicherblocks  unterbrochen.  Nach einer Unterbrechung kann
  1516.     die Ausführung durch <CTRL-RETURN>  fortgesetzt werden.
  1517.     Der Befehl ' ¿ AL-'Z' ' verhindert die Fortsetzung falls der letzte
  1518.     Block erreicht ist, da dieser als Kennzeichen  das Zeichen  'Z' be-
  1519.     sitzt. Bei allen anderen Blöcken ist das Kennzeichen 'M'.
  1520.  
  1521.  
  1522.     Durchlaufen der MCB-Kette
  1523.  
  1524.     Im Interpreter den Befehl
  1525.  
  1526.          D M2
  1527.  
  1528.     eingeben,  diesen  über die  Taste <ESC>  verlassen  und  die Taste
  1529.     <Home> betätigen.
  1530.  
  1531.     Oder im  Monitor auf  einem Byte,  das  nicht den Wert 04Dh (= 'M')
  1532.     enthält, die Taste <M> betätigen.
  1533.  
  1534.     Die Kette  der MCBs  kann nun  im Monitor durch wiederholte Eingabe
  1535.     der Taste <M> durchlaufen werden.
  1536.  
  1537.     Im  Interpreter kann  die Kette  der MCBs  durch  folgende  Befehle
  1538.     durchlaufen werden:
  1539.  
  1540.          ADD OF,3 ^ ADD SE,[OF] ^ + SE ^ MOV OF,0 ^ W
  1541.     oder:
  1542.          ADD SE,[OF+3] ^ + SE ^ M BL,[OF] ^ ¿ (BL-'Z') ^ W
  1543.  
  1544.     Durch  die Eingabe  von <Backspace> auf den  W-Befehl  wird nun die
  1545.     Kette der MCBs  durchlaufen.  Der ¿-Befehl  beendet  die Ausführung
  1546.     nach dem letzten MCB.
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.     ────────────────────────────────────────────────────────────────────────────────
  1560.                                                                         Seite   22
  1561.  
  1562.  
  1563.  
  1564.     ■ Durchlaufen  der  Kette  der  MCBs im Interpreter mit Anzeige der
  1565.       Besitzer jedes Blocks
  1566.  
  1567.          Vorbereitung:
  1568.  
  1569.          D M2 ^ MOV R7,SE      @ R7 = Zwischenspeicher für akt. MCB
  1570.  
  1571.          Die Kette der MCBs kann nun durch folgende Befehlsfolge, unter
  1572.          Anzeige der Besitzer der Blöcke, durchlaufen werden:
  1573.  
  1574.          M SE,R7^A SE,[OF+3]^+ SE^M R7,SE^W^ M SE,SE+1:[2C]^W
  1575.          ─────── ──────────────── ─────── ─  ────────────── ─
  1576.          (1)     (2)              (3)    (4) (5)            (6)
  1577.  
  1578.     Durch  den  Befehl 'M SE,R7' (1)  wird zuerst  der  Monitor auf die
  1579.     Adresse  des  aktuellen MCB gesetzt. Danach wird durch  die Befehle
  1580.     'A SE,[OF+3] ^ + SE' (2)  im Register  SE  die Adresse des nächsten
  1581.     MCB  ermittelt. Durch den Befehl 'M R7,SE' (3)  wird diese dann  im
  1582.     Register R7 gesichert. Der  MCB wird  nun angezeigt (4).  Falls auf
  1583.     den  W-Befehl (4) die Taste <Backspace>  betätigt wird, wird sofort
  1584.     der nächste MCB angezeigt. Jede  andere Taste,  außer  <ESC>  führt
  1585.     dazu,  daß  über die Befehls-Folge 'M SE,SE+1:[2C]' (5)  zuerst der
  1586.     dem Block zugehörige Environmentblock angezeigt wird. Falls auf den
  1587.     zweiten W-Befehl  (6) <Backspace> betätigt  wird,  wird der nächste
  1588.     MCB angezeigt.   Da nur Hauptblöcke ein  Environment haben, ist die
  1589.     Eingabe  von <Backspace>  auf den ersten W-Befehl (4) nur  sinnvoll
  1590.     wenn das Wort am Offset OF+1 ungleich Null (Block ist frei) und un-
  1591.     gleich  08 (Block gehört zu DOS) ist.
  1592.     Außerdem muß  der Wert beim Offset  OF+1  gleich SE+1 sein, da der
  1593.     Block  sonst kein  Hauptblock ist.  Die Eingabe einer anderen Taste
  1594.     als  <ESC> oder <Backspace> auf  den  ersten W-Befehl,  falls diese
  1595.     Bedingungen nicht erfüllt sind, zeigt nur unsinnige Daten an.
  1596.  
  1597.  
  1598.  
  1599.  
  1600.  
  1601.  
  1602.  
  1603.  
  1604.  
  1605.  
  1606.  
  1607.  
  1608.  
  1609.  
  1610.  
  1611.  
  1612.  
  1613.  
  1614.  
  1615.  
  1616.  
  1617.  
  1618.  
  1619.     ────────────────────────────────────────────────────────────────────────────────
  1620.                                                                         Seite   23
  1621.  
  1622.  
  1623.  
  1624.     Graphisch  dargestellt ergibt sich also bei der Annahme das  der zu
  1625.     untersuchende MCB einem Programm gehört, daß  sein Environment noch
  1626.     nicht freigegeben hat, folgendes:
  1627.  
  1628.         zu untersuchender MCB (1)
  1629.  
  1630.                      ┌─> Länge des zugehörigen Blocks
  1631.                      │
  1632.         ┌───┬──────┬──────┬──────────────────────────┐
  1633.         │ M │ nnnn │ mmmm │ bei DOS 3.xx freier Rest │
  1634.         └───┴──────┴──────┴──────────────────────────┘
  1635.               ║
  1636.     ╔═════════╝
  1637.     ║
  1638.     ║    MCB des Hautpblocks (2)
  1639.     ║   ┌───┬──────┬──────┬──────────────────────────┐
  1640.     ║   │ M │ nnnn │ mmmm │ bei DOS 3.xx freier Rest │
  1641.     ║   └───┴──────┴──────┴──────────────────────────┘
  1642.     ║          ║
  1643.     ╠<═════════╝
  1644.     ╠<═══════════════════════════════════════════════════╗
  1645.     ║    PSP des Hauptblocks (folgt direkt auf den MCB 2)║
  1646.     ║                   Offset 2Ch                       ║
  1647.     ║   ┌────┬────┬─────┬──────┬───┐                     ║
  1648.     ╚══>│ CD │ 20 │ ... │ nnnn │...│                     ║
  1649.         └────┴────┴─────┴──────┴───┘                     ║
  1650.                            ║                             ║
  1651.     ╔══════════════════════╝                             ║
  1652.     ║    MCB des Environments des Hauptblocks (3)        ║
  1653.     ║   ┌───┬──────┬──────┬──────────────────────────┐   ║
  1654.     ║   │ M │ nnnn │ mmmm │ bei DOS 3.xx freier Rest │   ║
  1655.     ║   └───┴──────┴──────┴──────────────────────────┘   ║
  1656.     ║          ║                                         ║
  1657.     ║          ╚═════════════════════════════════════════╝
  1658.     ║
  1659.     ║    Environment des Hauptblocks (folgt direkt auf den MCB 3)
  1660.     ║   ┌──────┬──────┬──────────────────────────────┐
  1661.     ╚══>│ ...  │ 0001 │ Name des Besitzers           │
  1662.         └──────┴──────┴──────────────────────────────┘
  1663.  
  1664.         Hierbei  können die MCBs 1 und 2 oder 1 und 3 jeweils identisch
  1665.         sein.
  1666.  
  1667.  
  1668.  
  1669.  
  1670.  
  1671.  
  1672.  
  1673.  
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.     ────────────────────────────────────────────────────────────────────────────────
  1680.                                                                         Seite   24
  1681.  
  1682.  
  1683.  
  1684.     Benutzung von MDEBUG für das Debuggen von eigenen Programmen
  1685.     ────────────────────────────────────────────────────────────
  1686.  
  1687.     MDEBUG eignet  sich  am  besten  zur  Anzeige und  Manipulation von
  1688.     Datenstrukturen von Programmen.
  1689.  
  1690.     MDEBUG  kann zum  Debuggen von  eigenen  Programmen  benutzt werden
  1691.     indem an den zu überprüfenden Stellen der Code zum Aufruf des User-
  1692.     Ints von MDEBUG eingefügt wird.
  1693.     Falls  verschiedene  Variablen  des  Programmes  untersucht  werden
  1694.     sollen, können die Adressen dieser vorher in die Prozessor-Register
  1695.     geladen werden oder aber über den Aufruf der Funktion 01h des User-
  1696.     Ints in die  Hilfsregister von MDEBUG geladen werden.
  1697.     (siehe TESTMD.PAS).
  1698.     Falls  in den  Registern SS  oder SP  Parameter  übergeben  werden,
  1699.     sollte  in MDEBUG vor  der Änderung dieser Register KEIN B-, I-, C-
  1700.     oder G-Befehl ausgeführt werden!
  1701.  
  1702.     Der aktuelle User-Int von MDEBUG sollte nicht als Konstante  einge-
  1703.     tragen,  sondern  während der Laufzeit ermittelt werden.
  1704.     Turbo-Pascal 5.0  z.B. mißbraucht den Interrupt 60h in der Entwick-
  1705.     lungsumgebung  für eigene Zwecke, so daß,  falls der  Interrupt 60h
  1706.     als User-Int von MDEBUG  installiert ist,  ein Aufruf  des User-Int
  1707.     aus  der Entwicklungsumgebung heraus zum Systemabsturz führt!
  1708.  
  1709.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.  
  1724.  
  1725.  
  1726.  
  1727.  
  1728.  
  1729.  
  1730.  
  1731.  
  1732.  
  1733.  
  1734.  
  1735.  
  1736.  
  1737.  
  1738.  
  1739.     ────────────────────────────────────────────────────────────────────────────────
  1740.                                                                         Seite   25
  1741.